<template>
  <div>this is test page</div>
</template>

<script lang="ts" setup>
import { reactive, ref, watch } from "vue";
interface Person {
  name: string;
  age: number;
}
// keyof 操作符可以用来一个对象中的所有 key 值, 返回的是这些key值得联合类型。
// type K1 = keyof Person; // 值只能是 "name" | "age"
// let str1: K1 = "name";
// K2 的类型是 string 或 number
type K2 = keyof { [propName: string]: Person };

type Keys = "a" | "b";
/**
 * in 用来遍历枚举类型
 * Obj1 的类型是 {a:string, b:string}
 */
type Obj1 = {
  [propName in Keys]: string;
};

/**
 * 在条件类型语句中,
 * 用infer声明一个类型变量
 * 并对它使用
 * 返回数组的第一项
 */
type Header<T extends Array<any>> = T extends [head: infer H, ...rest: any[]]
  ? H
  : never;
// never
// type H0 = Header<[]>;
// // 'string'
// type H1 = Header<['string',4]>

// extends
// type User = {
//   id: number;
//   name: string;
// };
// // 泛式T继承User, 必须拥有 User中的类型，但不局限只拥有
// function makeUser<T extends User>(u: T): T {
//   return {
//     ...u,
//     id: u.id,
//     kind: "123",
//   };
// }

interface User {
  name: string;
  age: number;
}
// type MyPartial<T> = {
//     [P in keyof T]?:T[P]
// }
// Partial<T> 的作用就是将某个类型里的属性全部变成可选
type optional1 = Partial<User>;
// **********************************

// type MyRequired<T> = {
//     [P in keyof T]-?:T[P]
// }
// Required<T> 的作用就是将某个类型中的属性全部变为必选
type require1 = Required<optional1>;
// **********************************

// type MyReadonly<T> = {
//     readonly [P in keyof T]:T[P]
// }
// readonly<T> 的作用是将某个类型所有属性变为只读属性，也就意味着这些属性不能被重新赋值。
type readonly1 = Readonly<User>;
// type RemoveReadonly<T> = {
//     -readonly [P in keyof T]:T[P]
// }
// // 移除readonly
// type removeReadonly1 = RemoveReadonly<readonly1>;
// **********************************

// Record<K extends keyof any,T> 的作用是将 K 中所有的属性的值转换为 T 类型
// type MyRecord<K extends keyof any, T> = {
//   // 将K中所有类型的属性进行遍历，再将每个Key赋值T类型 实例
//   [P in K]: T;
// };
type petsGroup = "dog" | "cat";
interface PertInfo {
  name: string;
}
type pets = Record<petsGroup, PertInfo>;
// **********************************

// Pick<T,K extends keyof T> 的作用是将某个类型中的子属性挑出来，变成包含这个类型部分属性的子属性
// type MyPick<T, K extends keyof T> = {
//   [P in K]: T[P];
// };
interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
type todo1 = Pick<Todo, "title" | "completed">;
// **********************************

// Exclude<T,U> 的作用是将某个类型中属于另一个的类型移除掉
// 如果 T 能赋值给 U 类型的话，那么就会返回 never 类型，否则返回 T 类型。
// type MyExclude<T, U> = T extends U ? never : T;
// type t0 = Exclude<"a" | "b" | "e", "a" | "c">;
type t1 = Exclude<string | number | (() => void), Function>;
// **********************************

// Omit<T, K extends keyof any> 的作用是使用 T 类型中除了 K 类型的所有属性
// type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
// 对于上面的 todo1 实现同样的效果
type todo2 = Omit<Todo, "description">;
// **********************************

// Extract<T, U>提取联合类型T和联合类型U的所有交集。
// type MyExtract<T, U> = T extends U ? T : never;
type ex1 = Extract<"key1" | "key2" | "key3", "key1">;
// **********************************
</script>
